#include "GZP6847.h"
#include "sys.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"
#include "timer.h"

//ADC采样说明

//1）ADC接在APB2上，时钟为72MHz，通过分频的方式给ADC 提供时钟，预分频有2、4、6、8 四种方式。
//2）通道采样时间，通道采样时间会影响采样的精度。
//3）转换时间		公式：TCONV = 采样时间+ 12.5 个周期 
//		例如：当ADCCLK=14MHz 和1.5 周期的采样时间   TCONV = 1.5 + 12.5 = 14 周期 = 1μs
//		1）一般情况，如果是软件启动，那么转换时间即是采样周期。
//		2）若通过定时器进行触发启动ADC，则还需要加上定时器的相关时间。
//4）确定采样率
//		1）如果采样率要达到400KHz，为了达到最好的精度，我们选取ADC时钟为12MHz，即6分频。
//在12MHz 以及保证采样率的情况下，采样时间越长其，准确性就越好，每次采样时间为1000000us/400000HZ = 2.5us。
//		2）可以计算 2.5us = （12.5 + 采样时间）/ 12MHz ，可以求得采样时间为17.5；所以采样时间的选择
//必须小于等于17.5个周期，才能保证采样率在400KHz 以上。所以我们可以选择1.5、7.5、13.5，为获得更
//高的精准度，我们可以选择13.5个周期。切记采样点数必须达到要求

/*
假设系统主频72M。
RCC_ADCCLKConfig(RCC_PCLK2_Div6);那么ADC的时钟就是12M。
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1,ADC_SampleTime_239Cycles5);
采样率为  12M/（239.5+12.5）=47.619KHz
STM32 ADC的时钟不要超过14MHz，否则转换精度会下降。
*/

unsigned char Press_TEST_FLAG = 0;//血压测量阶段 0：未开始 1：加压阶段 2：缓慢泄压阶段 

/// @brief 袖带式血压计初始化
/// @param  
void GZP6847Init(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口时钟


		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;				 
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;		 //IO口速度为2MHz
		GPIO_Init(GPIOA,&GPIO_InitStructure);
        SOLENOID = SOLENOID_OFF;

        TIM3_PWM_Init(100,300);
        Motor_Ctrl(MOTOR_OFF);
        Motor_Levle(90);


        //ADC初始化

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO, ENABLE);
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);//分频   设置adc时钟分频 为了达到最好的精度，我们选取ADC时钟为12MHz，即6分频
        ADC_DeInit(ADC1);//复位ADC1，设为缺省值
		GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;       //adc输入引脚
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;   //模拟输入 
		GPIO_Init(GPIOA,&GPIO_InitStructure);
		
		ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;     //独立模式
		//ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;     //ADC同步 1 2 DMA用

		ADC_InitStructure.ADC_ScanConvMode = DISABLE; 		//数模转换：扫描（多通道）模式=ENABLE  单次（单通道）模式=DISABLE
		//ADC_InitStructure.ADC_ScanConvMode = ENABLE;          //数模转换：扫描（多通道）模式=ENABLE  单次（单通道）模式=DISABLE

		ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;     //连续执行还是单次执行 定时器触发需要关闭
		//ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;     //DISABLE单次模式，enable连续执行模式 

		//ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;   //触发方式 定时器4 CC4
		ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   //触发方式 软件
		
		ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   //数据右对齐
		ADC_InitStructure.ADC_NbrOfChannel = 1;                 //顺序进行规则转换的通道数  
		ADC_Init(ADC1, &ADC_InitStructure);
	
		//设置指定ADC的规则组通道，设置它们的转化顺序和采样时间239.5T
		ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5 );
		//ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5 ); //内部参考通道

		//ADC_DMACmd(ADC1, ENABLE);//开启DMA ADC采集

        //ADC校准
		ADC_Cmd(ADC1,ENABLE);
		ADC_ResetCalibration(ADC1);//重新指定adc校准寄存器		
		while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC校准完成
		ADC_StartCalibration(ADC1);//开始指定adc校准状态
		while(ADC_GetCalibrationStatus(ADC1));//等待指定adc的校准程序完成	
		
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或者失能指定的ADC的软件转换启动功能	

		//ADC_ExternalTrigConvCmd(ADC1, ENABLE);//开启外部触发模式使能
		
		//ADC_TempSensorVrefintCmd(ENABLE); //开启内部参考电压 1.2V 使用内部参考电压计算电量百分比

}


static u16 Get_Adc1(void)
{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能软件转换功能
		while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
		return ADC_GetConversionValue(ADC1); //返回最近一次 ADC1 规则组的转换结果
}

/// @brief 获取气压传感器采样值
/// @param AveNum 均值滤波次数
/// @return 采样值
u16 GetGZP6847Num(u8 AveNum)
{
    		u32 temp_val=0;
		u8 t;
		for(t=0;t<AveNum;t++)
		{ 
				temp_val+=Get_Adc1();
				//delay_ms(5);
		}
		return temp_val/AveNum;
}





 
//电机档位控制
void Motor_Levle(u16 level) //等级  1- 99
{	
		if(level<1 || level>99)
				return;
		TIM3->CCR1	= level;
}
//电机启停设置
void Motor_Ctrl(u8 ctrl)
{	
		if(ctrl)
				TIM_CCxCmd(TIM3,TIM_Channel_1, ENABLE);	//开启电机
		else
				TIM_CCxCmd(TIM3,TIM_Channel_1, DISABLE);	//关闭电机
}
//电磁阀设置
void Solenoid_Ctrl(u8 ctrl) 
{	
		if(ctrl)
				SOLENOID =SOLENOID_ON;	//开启电磁阀
		else
				SOLENOID =SOLENOID_OFF;	//关闭电磁阀
}
